﻿using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Logging;
using NewRetail.Application.Components.Platform.Entity;
using NewRetail.Application.Components.Warehouse;
using NewRetail.Application.Core;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Volo.Abp.Application.Services;
using Volo.Abp.Domain.Repositories;
using Volo.Abp.Uow;

namespace NewRetail.Application.Components.Platform
{
    public class PosMemberPagingDto : PagingRequestDto
    {
        public string cardNo { get; set; }
        public string name { get; set; }
        public string phone { get; set; }

        public string warehouseId { get; set; }
        public string memberTypeId { get; set; }
        public bool available { get; set; }
    }

    public class PosIntergralPagingDto : PagingRequestDto
    {
        public string memberName { get; set; }
        public string memberNo { get; set; }
        public string memberTel { get; set; }

        public bool HasMemberCondition() =>
            !string.IsNullOrWhiteSpace(this.memberName) ||
            !string.IsNullOrWhiteSpace(this.memberNo) ||
            !string.IsNullOrWhiteSpace(this.memberTel);
    }

    public class MemberIntegralAdjustDto
    {
        /// <summary>
        /// 会员Id
        /// </summary>
        public string memberId { get; set; }
        /// <summary>
        /// 调整积分
        /// </summary>
        public decimal adjustIntegral { get; set; }
        /// <summary>
        /// 增加或减少(true 增加  false减少)
        /// </summary>
        public bool addOrMinus { get; set; }
        /// <summary>
        /// 备注说明
        /// </summary>
        public string remark { get; set; }
    }

    public interface IPosMemberService : IApplicationService
    {
        Task<PosMember[]> AttachWarehouse(PosMember[] data);
        Task<PosMember[]> AttachCashier(PosMember[] data);
        Task<PosMember[]> AttachMemberType(PosMember[] data);
        Task<PosIntegral[]> AttachPosMember(PosIntegral[] data);
        /// <summary>
        ///  会员积分调整
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        Task<string> PosMemberIntegralAdjust(MemberIntegralAdjustDto inputDto);
    }

    public class PosMemberService : MyApplicationService, IPosMemberService
    {
        private readonly ILogger logger;
        private readonly IRepository<PosMember> posMembers;
        private readonly IRepository<PosIntegral> _posIntegralRep;
        public PosMemberService(ILogger<PosMemberService> logger, IRepository<PosMember> posMembers, IRepository<PosIntegral> posIntegralRep)
        {
            this.logger = logger;
            this.posMembers = posMembers;
            _posIntegralRep = posIntegralRep;
        }

        public async Task<PosMember[]> AttachWarehouse(PosMember[] data)
        {
            var db = await this.posMembers.GetDbContextAsync();

            await db.AttachData<Warehouse.Entity.Warehouse, PosMember>(data,
                idGetter: x => x.sourceWarehouseID,
                action: (m, arr) => m.Warehouse = arr.FirstOrDefault());

            return data;
        }

        public async Task<PosMember[]> AttachCashier(PosMember[] data)
        {
            var db = await this.posMembers.GetDbContextAsync();

            await db.AttachData<PosCashier, PosMember>(data,
                idGetter: x => x.cashierID,
                action: (m, arr) => m.PosCashier = arr.FirstOrDefault());

            return data;
        }

        public async Task<PosMember[]> AttachMemberType(PosMember[] data)
        {
            var db = await this.posMembers.GetDbContextAsync();

            await db.AttachData<PosMemberType, PosMember>(data,
                idGetter: x => x.memberTypeID,
                action: (m, arr) => m.PosMemberType = arr.FirstOrDefault());

            return data;
        }

        public async Task<PosIntegral[]> AttachPosMember(PosIntegral[] data)
        {
            var db = await this.posMembers.GetDbContextAsync();

            await db.AttachData<PosMember, PosIntegral>(data,
                idGetter: x => x.memberID,
                action: (m, arr) => m.PosMember = arr.FirstOrDefault());

            return data;
        }
        /// <summary>
        ///  会员积分调整
        /// </summary>
        /// <param name="inputDto"></param>
        /// <returns></returns>
        public async Task<string> PosMemberIntegralAdjust(MemberIntegralAdjustDto inputDto)
        {
            using var uow = this.UnitOfWorkManager.Begin(requiresNew: true);
            var db = await this.posMembers.GetDbContextAsync();
            try
            {
                var member = await db.Set<PosMember>().FirstOrDefaultAsync(x => x.Id == inputDto.memberId);
                if (member == null)
                    return "会员不存在";

                var memberIntegral = new PosIntegral()
                {
                    memberID = inputDto.memberId,
                    integralSource = "积分调整",
                    plusOrMinus = inputDto.addOrMinus,
                    operateTime = this.Clock.Now,
                    integral = inputDto.adjustIntegral,
                    remark = inputDto?.remark
                };

                this.EntityHelper.InitEntity(memberIntegral);
                await _posIntegralRep.InsertAsync(memberIntegral);

                await uow.CompleteAsync();
                //发送通知来处理会员积分，通知订阅。实际就是调用MemberIntegralWorker的订阅OnMessage方法
                var svc = this.LazyServiceProvider.LazyGetRequiredService<IDataSyncService>();
                var mbIntegralArr = new List<PosIntegral>();
                mbIntegralArr.Add(memberIntegral);
                await svc.QueueDataSync(mbIntegralArr.ToArray());
            }
            catch (Exception e)
            {
                await uow.RollbackAsync();
                this.logger.LogError(message: e.Message, exception: e);
                throw;
            }
            return "";
        }
    }
}
